//
// Created by 吴喆 on 2020/3/5.
//

#include "Playable.h"
#include "Gui.h"

Playable::Playable(const Scene *scene_, DIRECTION direction) : GameObject(scene_) {
    GameObject::direction = direction;
}

void Playable::update() {
    GameObject::currPosition = GameObject::initPosition +
                               glm::vec2(-(body.currentPos - body.startPos).x, (body.currentPos - body.startPos).y);
    GameObject::currCenterPosition = currPosition + GameObject::size / 2;

    // step
    body.currentPos = glm::vec2(body.instance->GetPosition().x, body.instance->GetPosition().y);
    for (auto m : machines) {
        m->update(*this);
    }
    if (body.sensor != nullptr) {

        body.sensor->SetTransform(b2Vec2(body.instance->GetPosition().x, GameObject::currPosition.y + 1), 0);
        Gui::getInstance()->showPlayerPos(body.sensor->GetPosition().x, body.sensor->GetPosition().y);
    }
    body.lastPos = body.currentPos;
}

void Playable::handleInput(KeyEvent *event) {
    for (auto m : machines) {
        m->handleInput(*this, event);
    }
}

Playable::~Playable() {
    for (auto m : machines) {
        delete m;
    }
    body.instance->GetWorld()->DestroyBody(body.instance);
    if (body.sensor != nullptr) {
        body.sensor->GetWorld()->DestroyBody(body.sensor);
    }
}

void Playable::initBox() {
    b2BodyDef bodyDef;
    bodyDef.userData = this;
    bodyDef.type = b2_dynamicBody;
    body.startPos = glm::vec2(-GameObject::size.x / 2.0f - GameObject::initPosition.x,
                              GameObject::initPosition.y + 0.0000000000000001);
    body.currentPos = glm::vec2(-GameObject::size.x / 2.0f - GameObject::initPosition.x,
                                GameObject::initPosition.y + 0.0000000000000001);
    bodyDef.position.Set(body.startPos.x, body.startPos.y);
    body.instance = scene->world->createBody(&bodyDef);
    body.instance->SetFixedRotation(true);

//    dynamicBox.Set(b2Vec2(0,0), b2Vec2(0,0000000000000001));
    body.dynamicBox.SetAsBox(0.0000000000000001, 0.0000000000000001);
    // Define the dynamic body fixture.
    body.fixtureDef.shape = &body.dynamicBox;

    // Set the box density to be non-zero, so it will be dynamic.
    body.fixtureDef.density = 0.0f;

    // Override the default friction.
    body.fixtureDef.friction = 0.7f;
    // Add the shape to the body.
    body.instance->CreateFixture(&body.fixtureDef);
    body.instance->SetUserData(this);
    body.instance->SetAwake(false);

//    scene->world->b2world->SetContactListener(this);
}

void Playable::initSensorField() {
    b2BodyDef bodyDef;
    bodyDef.type = b2_kinematicBody;
    bodyDef.position.Set(body.startPos.x, GameObject::size.y / 2 + body.startPos.y);
    body.sensor = scene->world->createBody(&bodyDef);
    body.sensor->SetFixedRotation(true);
    b2PolygonShape dynamicBox;
    dynamicBox.SetAsBox(GameObject::size.x / 2, GameObject::size.y / 2);
    body.fixtureDef.isSensor = true;
    b2FixtureDef fixtureDef = body.fixtureDef;
    fixtureDef.shape = &dynamicBox;
    // Add the shape to the body.
    body.sensor->CreateFixture(&fixtureDef);
    body.sensor->SetUserData(this);
}
